// 窗口相关的方法
// 依赖 jquery

import { dataToStr } from './tool'

/**
 * 发送消息
 * @param {string} msgType 消息类型，如'openerData' || 'openerData.flag'，点号前面为实际类型，后面为标记符，主要用在getOpenerData
 * @param {*} data 发送的数据
 * @param {string} to 实际发送到
 * @param {window} target 发送到哪个页面window
 */
const postMessage = (msgType, data = {}, target = parent) => {
    if (!msgType || typeof msgType !== 'string') {
        console.warn('jqxt/win -> postMessage: 参数msgType不能为空，且必须是字符串')
        return
    }
    let d = {
        msgType,
        from: window.name,
        data
    }
    if (typeof target === 'object' && target.postMessage) {
        target.postMessage(d, '*')
    }
}

/**
 * 接收消息
 * @param {string} msgType 消息类型
 * @param {function} handler 处理函数
 */
const receiveMessage = (msgType, handler) => {
    if (!msgType || typeof msgType !== 'string') {
        console.warn('jqxt/win -> receiveMessage: 参数msgType不能为空，且必须是字符串')
        return
    }
    if (!handler || typeof handler !== 'function') {
        console.warn('jqxt/win -> receiveMessage: 参数handler不能为空，且必须是函数')
        return
    }
    const msgEventName = `message.${msgType}`
    $(window).off(msgEventName).on(msgEventName, () => {
        const data = window.event.data
        if (data && typeof data === 'object' && data.msgType.split('.')[0] === msgType) {
            handler(data)
        }
    })
}

/**
 * 打开窗口
 * @param {object} page 页面参数
 * @example
 * openWin({
 *     url: '',
 *     width: 1200,
 *     height: 600
 * })
 */
const openWin = p => {
    if (!p) {
        console.warn('jqxt/win -> openWin: 请传入参数')
        return
    }
    if (typeof p === 'string') {
        p = {
            url: p,
            width: 1200,
            height: 600
        }
    }
    if (p.url.startsWith("/")) { // 相对根路径
        p.url = window.location.origin + p.url
    } else if (!/^https?:\/\//gi.test(p.url)) { //相对路径
        const lhref = window.location.href.split('?')[0]
        p.url = lhref.slice(0, lhref.lastIndexOf('/') + 1) + p.url
    }
    postMessage('openWin', p)
}

/**
 * 从opener窗口取数据
 * @param {string} flag 调用标识，同一个页面flag必须不相同
 * @param {*} data 要取的数据, {key: keyType}，keyType说明：'var': 页面变量, 其它: jquery选择器(目前只支持input类型的value获取)
 * @param {Function} handler opener返回数据后的处理函数，接收取值后的data参数
 * @example
 * getOpenerData('a', {id1: '#id', id2: 'var'}, d => { console.log(d.id1) })
 */
const getOpenerData = (flag, data, handler) => {
    if (!flag || typeof flag !== 'string') {
        console.warn('jqxt/win -> getOpenerData: 参数flag不能为空，且必须是字符串')
        return
    }
    if (!data || typeof data !== 'object') {
        console.warn('jqxt/win -> getOpenerData: 参数data不能为空，且必须是对象')
        return
    }
    if (!handler || typeof handler !== 'function') {
        console.warn('jqxt/win -> getOpenerData: 参数handler不能为空，且必须是函数')
        return
    }
    postMessage(`getOpenerData.${flag}`, data)
    const msgEventName = `message.getOpenerDataRet.${flag}`
    $(window).off(msgEventName).on(msgEventName, () => {
        const data = window.event.data
        if (data && typeof data === 'object' && data.msgType === `getOpenerDataRet.${flag}`) {
            handler(data.data)
        }
        $(window).off(msgEventName)
    })
}

/**
 * 执行opener页面的全局方法，第1个参数为方法名，后面的参数为方法的参数
 * @param  {...any} args 
 */
const execOpenerFunc = (...args) => {
    if (args.length === 0) {
        console.warn('jqxt/win -> execOpenerFunc: 请传入要在opener页面执行的方法名')
        return
    }
    postMessage('execOpenerFunc', args)
}

const changeTitle = title => {
    if (!title || typeof title !== 'string') {
        return
    }
    postMessage('changeTitle', { title })
}

$(document).ready(() => {
    // 接收getOpenerData
    receiveMessage('getOpenerData', d => {
        const data = d.data.data;
        for (let item in data) {
            if (data[item] === 'var') {
                data[item] = window[item]
            } else {
                data[item] = $(data[item]).val()
            }
        }
        postMessage(d.msgType.replace('getOpenerData', 'getOpenerDataRet'), { to: d.data.to, data })
    })
    // 接收execOpenerFunc
    receiveMessage('execOpenerFunc', d => {
        let evalStr = ''
        for (let i = 0; i < d.data.length; i++) {
            const n = d.data[i]
            if (i === 0) {
                evalStr += n + '('
                continue
            }
            evalStr += dataToStr(n)
            if (i < d.data.length - 1) {
                evalStr += ','
            }
        }
        evalStr += ')'
        try {
            eval(evalStr)
        } catch (e) {
            console.error(`${d.from} 调用 ${window.name} 方法 ${evalStr} 失败，可能该方法不存在，或不是全局方法`)
        }
    })
    // 接收refreshPage
    receiveMessage('refreshPage', () => {
        window.location.reload()
    })
    // 根据document.title修改标题
    if (document.title !== '') {
        changeTitle(document.title)
    }
    // 点击置顶窗口
    if (window.name.indexOf('layui-layer-iframe') === 0) {
        $(document).off('click.layerTop').on('click.layerTop', () => {
            postMessage('layerTop')
        })
    }
})

export {
    postMessage,
    receiveMessage,
    openWin,
    getOpenerData,
    execOpenerFunc,
    changeTitle
}